﻿namespace NoIdeaIoc.Logger;
public class ConsoleLog : ILogger, IDisposable
{
    /// <summary>
    /// 开始生命周期
    /// </summary>
    /// <typeparam name="TState"></typeparam>
    /// <param name="state"></param>
    /// <returns></returns>
    public IDisposable BeginScope<TState>(TState state)
    {
        return this;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return true;
    }
    /// <summary>
    /// 记录日志
    /// </summary>
    /// <typeparam name="TState"></typeparam>
    /// <param name="logLevel"></param>
    /// <param name="eventId"></param>
    /// <param name="state"></param>
    /// <param name="exception"></param>
    /// <param name="formatter"></param>
    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
    {
        Log(nameof(ConsoleLog), $"{formatter(state, exception)}", exception, logLevel);
    }
    /// <summary>自定义记录日志</summary>
    /// <param name="eventSource">事件源</param>
    /// <param name="message">信息</param>
    /// <param name="exception">异常</param>
    /// <param name="infoLevel">null时自动判断等级</param>
    public void Log(string eventSource, string message, Exception exception, LogLevel? infoLevel = null)
    {
        if (exception != null)
        {
            logException(eventSource, message, exception);
        }
        else
        {
            if (message == null) return;
            LogLevel level;
            if (infoLevel.HasValue) level = infoLevel.Value;
            else level = LogLevel.Information;
            if (IsEnabled(level)) log(eventSource, message, level);
        }
    }
    void logException(string eventSource, string message, Exception exception)
    {
        if (IsEnabled(LogLevel.Error))
        {
            if (message == null || message.Length < 1) message = exception.Message;
            else message += $"{Environment.NewLine}{exception.Message}";
            log(eventSource, message, LogLevel.Error, exception.GetType().FullName, exception.StackTrace);
        }
    }
    void log(string eventSource, string message, LogLevel infoLevel, string exName = null, string stackTrace = null)
    {
        var thread = Thread.CurrentThread;
        var name = thread.Name;
        var tid = Task.CurrentId;
        var taskId = tid != null ? tid.Value : -1;
        if (string.IsNullOrEmpty(name)) name = taskId >= 0 ? taskId + "" : "-";
        else if (name.Equals("Threadpool worker", StringComparison.OrdinalIgnoreCase)) name = "P";
        else if (name.Equals("IO Threadpool worker", StringComparison.OrdinalIgnoreCase)) name = "IO";
        OnWrite(new InternalLogEntity
        {
            CreateTime = DateTime.Now,
            IsError = infoLevel == LogLevel.Critical || infoLevel == LogLevel.Error,
            LogLevel = infoLevel,
            Message = message,
            ExName = exName,
            StackTrace = stackTrace,
            Source = eventSource,
            TaskId = taskId,
            ThreadID = Thread.CurrentThread.ManagedThreadId,
            ThreadName = name,
            ThreadType = thread.IsThreadPoolThread ? "W" : "N"
        });
    }
    /// <summary>
    /// 写日志
    /// </summary>
    /// <param name="logEntity"></param>
    void OnWrite(InternalLogEntity logEntity)
    {
        Console.WriteLine(formatString(logEntity.ToString(), logEntity.LogLevel));
    }
    static string formatString(string msg, LogLevel level)
    {
        switch (level)
        {
            case LogLevel.Error:
                return ConsoleExtensions.Pastel(msg, "#f93a0d");
            case LogLevel.Critical:
                return ConsoleExtensions.Pastel(msg, Color.Red);
            case LogLevel.Information:
                return ConsoleExtensions.Pastel(msg, "#00c0ef");
            case LogLevel.Warning:
                return ConsoleExtensions.Pastel(msg, "#f39c12");
            case LogLevel.Trace:
                return ConsoleExtensions.Pastel(msg, "#8a7e7e");
            case LogLevel.None:
                return ConsoleExtensions.Pastel(msg, Color.Green);
            case LogLevel.Debug:
            default:
                return ConsoleExtensions.Pastel(msg, "#a78ddb");
        }
    }
    /// <summary>
    /// 释放资源
    /// </summary>
    public void Dispose()
    {
    }
}
public class ConsoleLog<T> : ILogger<T>, IDisposable
{
    public IDisposable? BeginScope<TState>(TState state) where TState : notnull
    {
        return this;
    }

    public bool IsEnabled(LogLevel logLevel)
    {
        return true;
    }
    readonly ConsoleLog console = new ConsoleLog();
    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
    {
        console.Log<TState>(logLevel, eventId, state, exception, formatter);
    }
    /// <summary>
    /// 释放资源
    /// </summary>
    public void Dispose()
    {
        console.Dispose();
    }
}